#include "JGLWidget.h"
#include "JLog.h"
#include "JProject.h"
//#include "JGLVideo.h"
#include "AviFile.h"

#include <QtOpenGL>

static CAviFile pAviFile(_T("Output.avi"), mmioFOURCC('C','V','I','D'), 30);
//static JGLVideo g_MovieRecorder( _T("Output.avi"), 640, 480);
//static STLModel m_Model("tibbone3_origin.stl"/*filename.toStdString()*/);
//static GLuint m_ModelDisplayList;


JGLWidget::JGLWidget(QWidget *parent, int nWidth, int nHeight)
	: QGLViewer(parent),
	//m_nMovieWidth(mWidth),
	//m_nMovieHeight(mHeight),
	//g_MovieRecorder(_T("Output.avi"), mWidth, mHeight),
	m_nWidth(nWidth),
	m_nHeight(nHeight),
	m_nBitsPerPixel(24),
	m_bIsRecording(false),
	showTibia(false)
{
	setMouseTracking(true);

	m_pBits = malloc(m_nWidth * m_nHeight * m_nBitsPerPixel/8);	/*create the required memory to hold the frame content*/
}

JGLWidget::~JGLWidget()
{
	if(m_pBits)
	{
		free(m_pBits);
		m_pBits = NULL;
	}
}

void JGLWidget::init()
{
	glClearColor(0.1, 0.1, 0.5, 0.1);
	//glClearColor(1, 1, 1, 1);

	GLfloat mat_specular[] = {.2, .2, .2, 1.0};
	GLfloat mat_shininess[] = {5};

	GLfloat light_position0[] = {0, 0, 2000, 0.0};
	GLfloat light_position1[] = {2000, 2000, 0, 0.0};
	GLfloat light_position2[] = {-2000, 2000, 0, 0.0};
	GLfloat light_position3[] = {0, 0, 0, 0.0};

	GLfloat light0[] = { .3, .3, .3, 1.0};
	GLfloat light1[] = { .3, .3, .3, 1.0};
	GLfloat light2[] = {.3, .3, .3, 1.0}; 
	GLfloat light3[] = {.3, .3, .3, 1.0};

	GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};

	glShadeModel(GL_SMOOTH);
	//glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

	glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, light0);
	glLightfv(GL_LIGHT0, GL_SPECULAR, light0);

	glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, light1);
	glLightfv(GL_LIGHT1, GL_SPECULAR, light1);

	glLightfv(GL_LIGHT2, GL_POSITION, light_position2);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, light2);
	glLightfv(GL_LIGHT2, GL_SPECULAR, light2);

	glLightfv(GL_LIGHT3, GL_POSITION, light_position3);
	glLightfv(GL_LIGHT3, GL_DIFFUSE, light3);
	glLightfv(GL_LIGHT3, GL_SPECULAR, light3);

	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHT1);
	glEnable(GL_LIGHT2);
	glEnable(GL_LIGHT3);
	//glEnable(GL_DEPTH_TEST);

	// Restore previous viewer state.
	//restoreStateFromFile();
	
	setSceneRadius(100.0); // set scene left/right dim to 50 units
	camera()->setZClippingCoefficient(4.0); // set scene front/back dim to 3*50 units
	camera()->setPosition(qglviewer::Vec(0,0,450));
}

void JGLWidget::preDraw()
{
	//
	QGLViewer::preDraw();
}

void JGLWidget::draw()
{
	//glPushMatrix();
	//glColor3f(.7,.7,.7);
	//glScalef(.1,.1,.1);
	//if(showTibia)
		//glCallList(m_ModelDisplayList);

	//drawAxis(2.0);
	//drawGrid(2.0,20);
	
}

void JGLWidget::postDraw()
{
	QGLViewer::postDraw();

	if (m_bIsRecording)
	{
		//if(FAILED(g_MovieRecorder.RecordFrame()))	/*Record the Rendered Frame into the Movie*/
		//{
		//	Log.Post("Error in RecordFrame", JLOG_ERROR);
		//	m_bIsRecording = false;
		//}
		glFlush();
		glFinish();
		glReadPixels(0, 0, m_nWidth, m_nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, m_pBits);
		pAviFile.AppendNewFrame(m_nWidth, m_nHeight, m_pBits, m_nBitsPerPixel);
	}
}

QDomElement JGLWidget::domElement(const QString& name, QDomDocument& document) const
{
	// Get default state domElement and append custom node
	QDomElement res = QGLViewer::domElement(name, document);
	res.appendChild(Project.Save(document));
	return res;
}

void JGLWidget::initFromDOMElement(const QDomElement& element)
{
	Project.Load(element);

	// Restore standard state
	QGLViewer::initFromDOMElement(element);

	updateGL();
}

QString JGLWidget::helpString() const
{
	QString text("<h2>Joint Mechanics 3D Viewer</h2>");
	text += "Use the mouse to move the camera around the object. ";
	text += "You can respectively revolve around, zoom and translate with the three mouse buttons. ";
	text += "Left and middle buttons pressed together rotate around the camera view direction axis<br><br>";
	text += "Pressing <b>Alt</b> and one of the function keys (<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
	text += "Simply press the function key again to restore it. Several keyFrames define a ";
	text += "camera path. Paths are saved when you quit the application and restored at next start.<br><br>";
	text += "Press <b>F</b> to display the frame rate, <b>A</b> for the world axis, ";
	text += "<b>Alt+Return</b> for full screen mode and <b>Control+S</b> to save a snapshot. ";
	text += "See the <b>Keyboard</b> tab in this window for a complete shortcut list.<br><br>";
	text += "Double clicks automates single click actions: A left button double click aligns the closer axis with the camera (if close enough). ";
	text += "A middle button double click fits the zoom of the camera and the right button re-centers the scene.<br><br>";
	text += "A left button double click while holding right button pressed defines the camera <i>Revolve Around Point</i>. ";
	text += "See the <b>Mouse</b> tab and the documentation web pages for details.<br><br>";
	text += "Press <b>Escape</b> to exit the viewer.";
	return text;
}

void JGLWidget::loadSTL( const QString& filename )
{

	showTibia = true;
	updateGL();
}

void JGLWidget::loadJTS( const QString& filename )
{
	updateGL();
}

void JGLWidget::beginRecordingMovie()
{
	//m_nWidth = width();
	//m_nHeight = height();

	resize(m_nWidth, m_nHeight);
	m_bIsRecording = true;
	Log.Post("Movie Recording Started");
}

void JGLWidget::stopRecordingMovie()
{
	if (!m_bIsRecording)
	{
		return;
	}
	m_bIsRecording = false;

	//resize(m_nWidth, m_nHeight);
	Log.Post("Movie Recording Stopped");
}